package projectAnalysis;

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

/**
 * 高级文件统计工具（支持按文件后缀筛选）
 * 该工具可以统计指定目录下所有文件（或按后缀筛选）的总大小（MB）、总行数（-1表示无法统计），
 * 并支持按后缀筛选文件（如 .java）。
 */
public class AdvancedFileStatistics {
    // 存储文件详细信息的内部类
    static class FileInfo {
        String path;       // 文件路径
        long sizeBytes;    // 大小（字节）
        int lineCount;     // 行数（-1表示无法统计）

        public FileInfo(String path, long sizeBytes, int lineCount) {
            this.path = path;
            this.sizeBytes = sizeBytes;
            this.lineCount = lineCount;
        }
    }

    public static void main(String[] args) {
        String dirPath = null;
        String suffix = null;

        // 解析命令行参数（支持格式：目录路径 [-s 后缀]）
        for (int i = 0; i < args.length; i++) {
            if (args[i].equalsIgnoreCase("-s") && i + 1 < args.length) {
                suffix = args[i + 1].toLowerCase();
                if (!suffix.startsWith(".")) {
                    suffix = "." + suffix; // 统一后缀格式（如"java"转为".java"）
                }
                i++; // 跳过后缀值
            } else if (dirPath == null) {
                dirPath = args[i];
            }
        }

        // 若命令行未提供目录，交互输入
        if (dirPath == null) {
            Scanner scanner = new Scanner(System.in);
            System.out.print("请输入要统计的目录路径: ");
            dirPath = scanner.nextLine().trim();

            System.out.print("是否指定文件后缀（如 .java，直接回车则不限制）: ");
            String inputSuffix = scanner.nextLine().trim().toLowerCase();
            if (!inputSuffix.isEmpty()) {
                suffix = inputSuffix.startsWith(".") ? inputSuffix : "." + inputSuffix;
            }
            scanner.close();
        }

        // 验证目录有效性
        File targetDir = new File(dirPath);
        if (!targetDir.exists()) {
            System.err.println("错误：目录不存在 -> " + dirPath);
            return;
        }
        if (!targetDir.isDirectory()) {
            System.err.println("错误：指定路径不是目录 -> " + dirPath);
            return;
        }

        // 收集文件信息
        List<FileInfo> fileInfos = new ArrayList<>();
        int[] dirCounter = new int[1]; // 目录计数器（用数组传递引用）
        System.out.println("\n正在扫描目录...（可能需要一段时间）");
        scanDirectory(targetDir, suffix, fileInfos, dirCounter);

        // 输出统计结果
        printStatistics(targetDir.getAbsolutePath(), suffix, fileInfos, dirCounter[0]);
    }

    /**
     * 递归扫描目录，收集符合条件的文件信息
     * @param currentFile 当前文件/目录
     * @param suffix 目标文件后缀（null表示不限制）
     * @param fileInfos 存储文件信息的列表
     * @param dirCounter 目录计数器
     */
    private static void scanDirectory(File currentFile, String suffix, List<FileInfo> fileInfos, int[] dirCounter) {
        if (currentFile.isDirectory()) {
            dirCounter[0]++; // 统计目录

            File[] files = currentFile.listFiles();
            if (files == null) {
                System.err.println("警告：无权限访问目录，已跳过 -> " + currentFile.getAbsolutePath());
                return;
            }

            for (File file : files) {
                if (file.isDirectory()) {
                    scanDirectory(file, suffix, fileInfos, dirCounter); // 递归处理子目录
                } else {
                    // 检查文件后缀是否符合条件
                    if (suffix == null || file.getName().toLowerCase().endsWith(suffix)) {
                        long size = file.length();
                        int lineCount = countFileLines(file); // 统计行数
                        fileInfos.add(new FileInfo(file.getAbsolutePath(), size, lineCount));
                    }
                }
            }
        }
    }

    /**
     * 统计文本文件的行数（二进制文件返回-1）
     * @param file 目标文件
     * @return 行数（-1表示无法统计）
     */
    private static int countFileLines(File file) {
        // 简单判断是否为文本文件（根据常见文本后缀，避免读取二进制文件）
        String name = file.getName().toLowerCase();
        if (name.endsWith(".zip") || name.endsWith(".rar") || name.endsWith(".exe") ||
            name.endsWith(".jpg") || name.endsWith(".png") || name.endsWith(".pdf") ||
            name.endsWith(".doc") || name.endsWith(".xls")) {
            return -1;
        }

        // 尝试读取行数（处理大文件时用缓冲流，避免内存溢出）
        int lines = 0;
        try (BufferedReader br = Files.newBufferedReader(Paths.get(file.getAbsolutePath()), StandardCharsets.UTF_8)) {
            while (br.readLine() != null) {
                lines++;
            }
            return lines;
        } catch (IOException e) {
            // 读取失败（如编码问题、文件损坏）
            return -1;
        }
    }

    /**
     * 格式化文件大小（自动转换为B/KB/MB/GB）
     * @param bytes 字节数
     * @return 格式化后的大小字符串
     */
    private static String formatSize(long bytes) {
        if (bytes < 1024) {
            return bytes + " B";
        } else if (bytes < 1024 * 1024) {
            return new DecimalFormat("#.##").format(bytes / 1024.0) + " KB";
        } else if (bytes < 1024 * 1024 * 1024) {
            return new DecimalFormat("#.##").format(bytes / (1024.0 * 1024)) + " MB";
        } else {
            return new DecimalFormat("#.##").format(bytes / (1024.0 * 1024 * 1024)) + " GB";
        }
    }

    /**
     * 打印统计结果（详细文件信息 + 汇总数据）
     */
    private static void printStatistics(String dirPath, String suffix, List<FileInfo> fileInfos, int dirCount) {
        System.out.println("\n\n===== 高级文件统计结果 =====");
        System.out.println("目标目录: " + dirPath);
        System.out.println("文件筛选条件: " + (suffix == null ? "所有文件" : "后缀为 " + suffix + " 的文件"));
        System.out.println("----------------------------------------");

        // 打印文件列表（对齐格式）
        System.out.printf("%-60s %12s %10s%n", "文件路径", "大小", "行数");
        System.out.println("------------------------------------------------------------------------------------------------");

        long totalSize = 0;
        int totalLines = 0;
        int textFileCount = 0;

        for (FileInfo info : fileInfos) {
            totalSize += info.sizeBytes;
            String lineStr = (info.lineCount == -1) ? "N/A" : String.valueOf(info.lineCount);
            if (info.lineCount != -1) {
                totalLines += info.lineCount;
                textFileCount++;
            }

            // 路径过长时截断显示（保留最后60个字符）
            String displayPath = info.path;
            if (displayPath.length() > 60) {
                displayPath = "..." + displayPath.substring(displayPath.length() - 57);
            }

            System.out.printf("%-60s %12s %10s%n", displayPath, formatSize(info.sizeBytes), lineStr);
        }

        // 打印汇总信息
        System.out.println("------------------------------------------------------------------------------------------------");
        System.out.println("\n【汇总统计】");
        System.out.printf("总文件数量: %,d 个%n", fileInfos.size());
        System.out.printf("其中文本文件数量: %,d 个（可统计行数）%n", textFileCount);
        System.out.printf("总文件大小: %s（%,d 字节）%n", formatSize(totalSize), totalSize);
        System.out.printf("总代码行数（文本文件）: %,d 行%n", totalLines);
        System.out.printf("总目录数量: %,d 个%n", dirCount);
        System.out.println("==========================");
    }
}